/*
 * $Id: SimpleCache.java 23 2002-09-29 13:59:30Z bpruessmann $
 * 
 * Copyright (c) 2001 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.p4eclipse.core.syncinfo;

import java.io.IOException;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import jdbm.JDBMEnumeration;
import jdbm.JDBMHashtable;
import jdbm.JDBMRecordManager;

import net.sourceforge.p4eclipse.core.Policy;

/**
  * @version 	$Revision: 23 $
  * @author		<a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class SimpleCache
{
	private JDBMRecordManager recordManager;
	private JDBMHashtable cache;
	private ICacheLoader loader;
	
	public static class CacheData implements Serializable
	{
		private Object  key;
		private Object  value;
		private Date    expirationDate;
		private boolean updated = true;
		
		public CacheData(Object key, Object value, int ttl)
		{
			Policy.assertNotNull(key);
			Policy.assertNotNull(value);			
			
			this.key = key;
			this.value = value;
			if (ttl > 0)
			{
				Calendar calendar = Calendar.getInstance();
				calendar.add(Calendar.MILLISECOND, ttl);
				expirationDate = calendar.getTime();
			}
		}
		
		public boolean isUpdated()
		{
			return updated;
		}
		
		public void setUpdated(boolean updated)
		{
			this.updated = updated;
		}		
		
		public boolean isExpired()
		{
			return expirationDate != null ?  expirationDate.before(new Date()) : false;
		}
		
		public Object getKey()
		{
			return key;
		}
		
		public Object getValue()
		{
			return value;
		}		
		
		public void setValue(Object value)
		{
			this.value = value;
		}
	}

	public static interface ICacheLoader
	{
		public CacheData load(Object key, SimpleCache cache)
			throws IOException;
	}

	public SimpleCache(JDBMRecordManager recordManager, String cacheName)
		throws IOException
	{
		this.recordManager = recordManager;
		this.cache = this.recordManager.getHashtable(cacheName);
	}
	
	public CacheData get(Object key)
		throws IOException
	{
		CacheData data = (CacheData)cache.get(key);
		if ((data == null && loader != null) || (data != null && data.isExpired()))
		{
			data = loader.load(key, this);
			if (data != null)
				put(data);
			else
				remove(key);
		}
		else
			data.setUpdated(false);
		
		return data;	
	}
	
	public void put(CacheData data)
		throws IOException
	{
		cache.put(data.getKey(), data);
	}
	
	public void remove(Object key)
		throws IOException
	{
		cache.remove(key);
	}
	
	public void registerLoader(ICacheLoader loader)
	{
		Policy.assertNotNull(loader);
		this.loader = loader;
	}
			
	public void clear()
		throws IOException	
	{
		for (JDBMEnumeration enum = cache.keys(); enum.hasMoreElements(); )
		{
			String key = (String)enum.nextElement();
			cache.remove(key);
		}
	}	
	
	/*
	public Iterator iterator()
	{
		return cache.entrySet().iterator();
	}	
	*/
}
